//虽然在js中，一切皆对象，但是由于js中没有类的概念，所以完全无法发挥面向对象编程的威力。

//所以js引入了原型的概念。


//假如我需要Cat这个类，它是个对象，属性是它的特征，方法是它的行为

var Cat={
    name:"",
    color:"",
    eat:function(){
        console.log("吃老鼠");
    }
}
console.log(Cat);

//得到了Cat这个类，那需要实例化它呢？？就是按Cat这个类的结构去 var出另一些Cat1、Cat2、Cat3等等

var Cat1={
    name:"小黄",
    color:"花黄色",
    eat:function(){
        console.log("吃老鼠");
    }
}
console.log(Cat1);

var Cat2={
    name:"大白",
    color:"白色",
    eat:function(){
        console.log("吃老鼠");
    }
}
console.log(Cat2);
//但是我们发现：
//1、“实例化”后的Cat1和Cat2之间好像没什么关系啊，和原型Cat更加没有关系啊，它们只是结构一样而已
//2、实例化一两个还好，但是实例化数据一多起来，产生的代码将是指数性增长，代码大量冗余


//有没有办法解决？
//可以用函数解决代码冗余，可以用构造函数解决Cat1指向原型的问题

var Cat=function(name,color,hobby){
    this.name=name;
    this.color=color;
    this.hobby=hobby;
    this.eat=function (){
        console.log("抓老鼠！");
    }

}
var Cat1=new Cat("小黑","纯黑色","爱好猫掸子");
console.log(Cat1);
console.log(Cat1.hobby);
Cat1.eat();//该方法是继承原型来的


//验证实例和原型之间是否有联系或者说验证该实例是不是继承于某个原型的，提供了两种方法
//1、实例.constructor == 原型
console.log(Cat1.constructor==Cat );

//2、实例  instanceof 原型
console.log(Cat1 instanceof  Cat);



//好了 代码冗余和实例指向的问题 得到了解决，又发现每new一个实例，就会开辟一个新的内存空间来存储属性方法等,
//当存在 大量相同的属性和方法 就会造成大量的内存浪费，效率低下，那能不能共同的属性和方法都由原型继承来？
//答案是可以的


// Prototype模式
//Javascript规定，每一个构造函数都有一个prototype属性，指向另一个对象。这个对象的所有属性和方法，都会被构造函数的实例继承。
//这意味着，我们可以把那些不变的属性和方法，直接定义在prototype对象上

//上面我们已经创建了一个原型——Cat，现在只将共同的属性和方法用prototype属性绑定
Cat.prototype.type="猫科动物";
Cat.prototype.naoyang=function(){
    console.log('我会挠痒！');
}

var Cat2=new Cat("小花","花色","爱好主人")
var Cat3=new Cat("小绿","绿色","爱好主人")
var Cat4= Cat("小绿","绿色","爱好主人")
console.log(Cat2);

//Cat2.type和Cat2.naoyang()都是指向原型的同一个内存空间，效率大大提高
console.log(Cat2.type);
Cat2.naoyang();

console.log(Cat2.type==Cat3.type);//是否来自同一内存空间


//1、isPrototypeOf()——验证原型中是否有的实例中是否有该实例
console.log(Cat.prototype.isPrototypeOf(Cat2));
console.log(Cat.prototype.isPrototypeOf(Cat4));

//验证实例
//2、hasOwnProperty()——用来判断某一个属性到底是本地属性，还是继承自prototype对象的属性
console.log(Cat2.hasOwnProperty("name"));
console.log(Cat2.hasOwnProperty("eat"));
console.log(Cat2.hasOwnProperty("type"));
console.log(Cat2.hasOwnProperty("naoyang"));


//in 运算符——检查属性是否属于某实例,不管是本身的还是继承来的
console.log("name" in Cat2);
console.log("type" in Cat2);








